﻿// http://ghtyan.cnblogs.com    代码供大家学习
    
    /**//*============================prototype.js中的部分函数================================*/
    Object.extend = function(destination, source) {
        for (property in source) destination[property] = source[property];
        return destination;
    }

    Function.prototype.bind = function(object) {
        var __method = this;
        return function() {
            return __method.apply(object, arguments);
        }
    }

    Function.prototype.bindAsEventListener = function(object) {
      var __method = this;
      return function(event) {
        return __method.call(object, event || window.event);
      }
    }

    function $() {
        if (arguments.length == 1) return get$(arguments[0]);
        function get$(el){
            if (typeof el == 'string') el = document.getElementById(el);
            return el;
        }
    }
    
    /**//*============================基础类================================*/
    function CPoint(x,y){   //坐标点
        this.x=x;
        this.y=y;
    }
    function CSize(width,height){  //矩形区域
        this.width=width;        
        this.height=height;        
    }
    function CBounds(p1,p2){  //矩形坐标范围，参数左上点和右下点组成
        this.minX=p1.x;        
        this.minY=p1.y;  
        this.maxX=p2.x;
        this.maxY=p2.y;      
        this.getSize=function(){
            return new CSize(this.maxX-this.minX,this.maxY-this.minY);
        }
    }
    window.CEvent={         //自定义事件处理
        addListener:function(obj,target,act){
        if(obj.attachEvent) obj.attachEvent("on"+target,act);
        if(obj.addEventListener) obj.addEventListener(target,act,false);
        },
        removeListener:function(obj,target,act){
        if(obj.detachEvent) obj.detachEvent("on"+target,act);
        if(obj.removeEventListener) obj.removeEventListener(target,act,false);
        }
    }
    
    /**//*============================地图类================================*/
    function CMap(div){
        this.holder=div;        //地图的载体，即窗口层
        this.config={
            imgsize:256        //小图边长
            }; 
        this._center;           //实时中心点
        this.mvl;               //用于移动的层，即移动层
        
        this.mouseopt={         //鼠标在地图上操作选项
            down:false,         //是否按下
            move:false,         //是否按下并移动过
            dx:0,dy:0,          //按下时移动层的left和top
            ex:0,ey:0           //按下时的事件坐标
            };
        this.mapimage=new Array();//当前显示的地图集合
        this.cacheimage=new Array();//图片对象缓存，避免重复创建和删除IMG对象
    }
    
    CMap.prototype = {
        _getimage:function(){//获取一个IMG对象
            var img =this.cacheimage.shift();
            if(img==null) {img=document.createElement("IMG");}
            return img;
        },
        _loadmap:function(){//加载地图
                
            var bounds=this.getBounds();
            var x1=Math.floor(bounds.minX/this.config.imgsize);
            var x2=Math.ceil(bounds.maxX/this.config.imgsize);
            var y1=Math.floor(bounds.minY/this.config.imgsize);
            var y2=Math.ceil(bounds.maxY/this.config.imgsize);
            
            this.mvl.style.left=-bounds.minX+"px";
            this.mvl.style.top=-bounds.minY+"px";
            for(var y=y1;y<y2;y++)
            {
                for(var x=x1;x<x2;x++)
                {
                    var img = this._getimage();
                    this.mapimage.push(img);
                    img.style.position="absolute";
                    img.style.backgroundColor="#AEAEAE";
                    img.style.left=x*this.config.imgsize+"px";
                    img.style.top=y*this.config.imgsize+"px";
                    img.style.width=this.config.imgsize+"px";
                    img.style.height=this.config.imgsize+"px";
                    img.alt=x+","+y;
                    this.mvl.appendChild(img);
                }
            }
        },
        _resize:function(evt){    //地图resize事件，内部函数
            
            this.onresize();
            this._clearmap();
            this._loadmap();
        },
        _mapmousedown:function(evt){
            //记录鼠标操作信息
            this.mouseopt.down=true;
            this.mouseopt.ex=evt.clientX;
            this.mouseopt.ey=evt.clientY;
            this.mouseopt.dx=this.mvl.offsetLeft;
            this.mouseopt.dy=this.mvl.offsetTop;
            
            //为了使鼠标移动到浏览器外部，事件依然有效，IE & firefox
            if(this.mvl.setCapture)   
              this.mvl.setCapture();   
            else  if(window.captureEvents)   
              window.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);
        },
        _mapmove:function(evt){
       
            if(this.mouseopt.down==true)
            {
                //拖动时记录鼠标拖动过以及设定移动层的位置
                this.mouseopt.move=true;
                this.mvl.style.left=this.mouseopt.dx+(evt.clientX-this.mouseopt.ex)+"px";
                this.mvl.style.top=this.mouseopt.dy+(evt.clientY-this.mouseopt.ey)+"px";
            }
        },
        _mapmouseup:function(evt){
            //取消事件捕捉
            if(this.mvl.releaseCapture)   
              this.mvl.releaseCapture();   
            else   if(window.releaseEvents)   
              window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP);
              
            if(this.mouseopt.down==true&&this.mouseopt.move==true)
            {
                //重新设定实时中心位置
                this._clearmap();
                this._center.x=this.holder.offsetWidth/2-this.mvl.offsetLeft;
                this._center.y=this.holder.offsetHeight/2-this.mvl.offsetTop;
                this._loadmap();
            }
            this.mouseopt.down=false;
            this.mouseopt.move=false;
        },
        _clearmap:function(){//清除当前地图图片，放入图片缓存
            var tm;
            while((tm=this.mapimage.pop())!=null){
                this.mvl.removeChild(tm);
                this.cacheimage.push(tm);
            }
        }
    }
    CMap.prototype.init=function(){
        //创建移动层
        this.holder.style.overflow="hidden";
        this.mvl=document.createElement("DIV");
        this.mvl.style.cssText="position:absolute;left:0;top:0;z-index:1";
        this.holder.appendChild(this.mvl);
        
        //创建遮盖层
        this.cover=document.createElement("DIV");
        this.cover.innerHTML="&nbsp;";
        this.cover.style.cssText="position:relative;left:0;top:0;z-index:2;width:2000px;height:2000px;background-color:gray;filter:alpha(opacity=0);opacity:0;";
        this.holder.appendChild(this.cover);
        
        this._loadmap();
        
        //事件绑定
        CEvent.addListener(window,"resize",this._resize.bindAsEventListener(this));
        CEvent.addListener(this.holder,"mousedown",this._mapmousedown.bindAsEventListener(this));
        CEvent.addListener(this.holder,"mousemove",this._mapmove.bindAsEventListener(this));
        CEvent.addListener(this.holder,"mouseup",this._mapmouseup.bindAsEventListener(this));
    }
    
    CMap.prototype.reload=function(){    //外部强制重新加载地图
        this._loadmap();
    }
    
    CMap.prototype.onresize=function(evt){    //地图resize事件，供外部定义函数
        
    }
    
    CMap.prototype.setCenter=function(p){
        this._center = p;
    }
    CMap.prototype.getCenter=function(){
        return this._center;
    }
    CMap.prototype.getBounds=function(){    //获取地图范围
        var p1= new CPoint(this._center.x-this.holder.offsetWidth/2,this._center.y-this.holder.offsetHeight/2);
        var p2= new CPoint(this._center.x+this.holder.offsetWidth/2,this._center.y+this.holder.offsetHeight/2)
        return new CBounds(p1,p2);
    }